import re

from google.appengine.ext import db

class NarisaUser(db.Model):
	userId = db.IntegerProperty()
	userName = db.StringProperty()
	vcKey = db.StringProperty()

	def __repr__(self):
		return self.__str__()

	def __str__(self):
		return 'NarisaUser[key:%s userId:%d userName:%s]' % (self.key(), self.userId, self.userName)

	@classmethod
	def add(cls, userId, userName, vcKey):
		user = NarisaUser.all().filter('userId =', userId).fetch(1)

		if (len(user) == 1):
			return False

		user = NarisaUser.all().filter('vcKey =', vcKey).fetch(1)

		if (len(user) == 1):
			return False

		newUser = NarisaUser()
		newUser.userId = userId
		newUser.userName = userName
		newUser.vcKey = vcKey
		newUser.put()

		return newUser

class Tag(db.Model):
	name = db.StringProperty()
	color = db.StringProperty()
	hits = db.IntegerProperty()

	def __repr__(self):
		return self.__str__()

	def __str__(self):
		return 'Tag[key:%s name:%s color:%s hits:%d]' % (self.key(), self.name, self.color, self.hits)

	def json(self):
		return {'tag':self.name, 'color':self.color, 'hits':self.hits}

	@classmethod
	def find(cls, tagName):
		tagName = re.sub('\s+', ' ', tagName.strip())

		oldTag = Tag.all().filter('name', tagName).fetch(1)

		if (len(oldTag) == 1):
			return oldTag[0]

		return None

	@classmethod
	def findOrCreate(cls, tagName, color = None):
		tagName = re.sub('\s+', ' ', tagName)

		# find old tag first
		oldTag = Tag.all().filter('name', tagName).fetch(1)

		if (len(oldTag) == 1):
			return oldTag[0]

		tag = Tag()
		tag.name = tagName
		tag.color = color
		tag.hits = 0
		tag.put()

		return tag

class TopicStat(db.Model):
	topicId = db.IntegerProperty()
	tag = db.ReferenceProperty(Tag)
	hits = db.IntegerProperty()

	def __repr__(self):
		return self.__str__()

	def __str__(self):
		return ('TopicStat[key:%s topicId:%d tag:%s hits:%d color:%s]'
				% (self.key(), self.topicId, self.tag.name, self.hits, self.tag.color))

	def json(self):
		return {'topicId':self.topicId, 'tag':self.tag.name, 'hits':self.hits, 'color':self.tag.color}

	@classmethod
	def topicTagHit(cls, tag, topicId):
		stat_query = TopicStat.all()
		stat_query.filter('topicId =', topicId)
		stat_query.filter('tag =', tag)

		stat = stat_query.fetch(1)

		if (len(stat) == 0):
			newStat = TopicStat()
			newStat.topicId = topicId
			newStat.tag = tag
			newStat.hits = 1
			newStat.put()
		else:
			stat[0].hits += 1
			stat[0].put()

	@classmethod
	def listByTag(cls, _tag):
		return TopicStat.all().filter('tag', _tag).order('-hits').fetch(100)

	@classmethod
	def listByTopics(cls, _topicIds):
		if (len(_topicIds) == 0):
			return []

		query = TopicStat.gql('WHERE topicId IN :topicIds ORDER BY hits DESC', topicIds=_topicIds)
		return query.fetch(10)

class TagHistory(db.Model):
	tag = db.ReferenceProperty(Tag)
	user = db.ReferenceProperty(NarisaUser)
	topicId = db.IntegerProperty()
	added = db.DateTimeProperty(auto_now_add = True)

	def __repr__(self):
		return self.__str__()

	def __str__(self):
		return ('TagHistory[key:%s tagName:%s user:%s topicId:%d]'
				% (self.key(), self.tag.name, self.user.userName, self.topicId))

	@classmethod
	def untagTopic(cls, tag, user, topicId):
		query = TagHistory.all()
		query.filter('tag =', tag)
		query.filter('user =', user)
		query.filter('topicId =', int(topicId))
		history = query.fetch(1)

		if (len(history) == 1):
			history[0].delete()

			stat = TopicStat.all().filter('topicId =', topicId).filter('tag =', tag).fetch(1)

			if (len(stat) == 1):
				# reduce hit count for this stat entry, if it's zero also remove this entry
				stat[0].hits -= 1

				if (stat[0].hits > 0):
					stat[0].put()
				else:
					stat[0].delete()

				# reduce hit count for this tag entry, if it's zero also remove this entry
				tag.hits -= 1

				if (tag.hits > 0):
					tag.put()
				else:
					tag.delete()

	@classmethod
	def tagTopic(cls, tagName, user, topicId, color = None):
		# find or create this tag first
		tag = Tag.findOrCreate(tagName, color)

		old_query = TagHistory.all()
		old_query.filter('tag =', tag)
		old_query.filter('user =', user)
		old_query.filter('topicId =', topicId)

		old = old_query.fetch(1)

		# duplicated ? return
		if (len(old) == 1):
			return

		history = TagHistory()
		history.tag = tag
		history.user = user
		history.topicId = topicId
		history.put()

		tag.hits += 1
		tag.put()

		TopicStat.topicTagHit(tag, topicId)

